package com.ly.web.controller.system;

import java.util.List;
import java.util.stream.Collectors;

import com.ly.common.annotation.Log;
import com.ly.common.constant.Constants;
import com.ly.common.constant.UserConstants;
import com.ly.common.core.controller.BaseController;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysMenu;
import com.ly.common.core.domain.model.LoginUser;
import com.ly.common.enums.BusinessType;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.ServletUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.framework.web.service.TokenService;
import com.ly.system.service.ISysMenuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 菜单管理
 *
 * @author
 */
@Api ( value = "SysMenu", tags = "菜单管理" )
@RestController
@RequestMapping ( "/system/menu" )
public class SysMenuController extends BaseController {
    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private TokenService tokenService;

    /**
     * 获取菜单列表
     */
    @PreAuthorize ( "@ss.hasPermi('system:menu:list')" )
    @GetMapping ( "/list" )
    @ApiOperation ( "获取菜单列表" )
    public AjaxResult list ( SysMenu menu ) {
        LoginUser loginUser = tokenService.getLoginUser ( ServletUtils.getRequest () );
        String userId = loginUser.getUser ().getUserId ();
        List<SysMenu> menus = menuService.selectMenuList ( menu, userId );
        return AjaxResult.success ( menus );
    }

    /**
     * 根据参数menuType和parentId获取对应的菜单和按钮列表
     */
    @GetMapping ( "/getMenu" )
    @ApiOperation ( "根据类型获取菜单和按钮列表" )
    public AjaxResult getMenu ( SysMenu menu ) {
        List<SysMenu> menus = menuService.getMenuList ( menu );
        return AjaxResult.success ( menus );
    }

    /**
     * 根据菜单编号获取详细信息
     */
    @ApiOperation ( "根据菜单编号获取详细信息" )
    @PreAuthorize ( "@ss.hasPermi('system:menu:query')" )
    @GetMapping ( value = "/{menuId}" )
    public AjaxResult getInfo ( @PathVariable String menuId ) {
        return AjaxResult.success ( menuService.selectMenuById ( menuId ) );
    }

    /**
     * 获取菜单下拉树列表
     */
    @ApiOperation ( "获取菜单下拉树列表" )
    @GetMapping ( "/treeselect" )
    public AjaxResult treeselect ( SysMenu menu ) {
        LoginUser loginUser = tokenService.getLoginUser ( ServletUtils.getRequest () );
        String userId = loginUser.getUser ().getUserId ();
        List<SysMenu> menus = menuService.selectMenuList ( menu, userId );
        return AjaxResult.success ( menuService.buildMenuTreeSelect ( menus ) );
    }

    /**
     * 加载对应角色菜单列表树
     */
    @ApiOperation ( "加载对应角色菜单列表树" )
    @GetMapping ( value = "/roleMenuTreeselect/{roleId}" )
    public AjaxResult roleMenuTreeselect ( @PathVariable ( "roleId" ) String roleId ) {
        LoginUser loginUser = tokenService.getLoginUser ( ServletUtils.getRequest () );
        List<SysMenu> menus = menuService.selectMenuList ( loginUser.getUser ().getUserId () );
        menus = menus.stream ().filter ( menu -> "1".equals ( menu.getHideRoute () ) ).collect ( Collectors.toList () );
        AjaxResult ajax = AjaxResult.success ();
        ajax.put ( "checkedKeys", menuService.selectMenuListByRoleId ( roleId ) );
        ajax.put ( "menus", menuService.buildMenuTreeSelect ( menus ) );
        return ajax;
    }

    /**
     * 新增菜单
     */
    @ApiOperation ( "新增菜单" )
    @PreAuthorize ( "@ss.hasPermi('system:menu:add')" )
    @Log ( title = "菜单管理", businessType = BusinessType.INSERT )
    @PostMapping
    public AjaxResult add ( @Validated @RequestBody SysMenu menu ) {
        if ( UserConstants.NOT_UNIQUE.equals ( menuService.checkMenuNameUnique ( menu ) ) ) {
            return AjaxResult.error ( "新增菜单'" + menu.getMenuName () + "'失败，菜单名称已存在" );
        } else if ( UserConstants.YES_FRAME.equals ( menu.getIsFrame () )
                && ! StringUtils.startsWithAny ( menu.getPath (), Constants.HTTP, Constants.HTTPS ) ) {
            return AjaxResult.error ( "新增菜单'" + menu.getMenuName () + "'失败，地址必须以http(s)://开头" );
        }
        menu.setMenuId ( SnowflakeIdWorker.getInstance ().nextStringId () );
        menu.setCreateBy ( SecurityUtils.getUsername () );
        return menuService.insertMenu ( menu );
    }

    /**
     * 修改菜单
     */
    @ApiOperation ( "修改菜单" )
    @PreAuthorize ( "@ss.hasPermi('system:menu:edit')" )
    @Log ( title = "菜单管理", businessType = BusinessType.UPDATE )
    @PutMapping
    public AjaxResult edit ( @Validated @RequestBody SysMenu menu ) {
        if ( UserConstants.NOT_UNIQUE.equals ( menuService.checkMenuNameUnique ( menu ) ) ) {
            return AjaxResult.error ( "修改菜单'" + menu.getMenuName () + "'失败，菜单名称已存在" );
        } else if ( UserConstants.YES_FRAME.equals ( menu.getIsFrame () )
                && ! StringUtils.startsWithAny ( menu.getPath (), Constants.HTTP, Constants.HTTPS ) ) {
            return AjaxResult.error ( "修改菜单'" + menu.getMenuName () + "'失败，地址必须以http(s)://开头" );
        } else if ( menu.getMenuId ().equals ( menu.getParentId () ) ) {
            return AjaxResult.error ( "修改菜单'" + menu.getMenuName () + "'失败，上级菜单不能选择自己" );
        }
        menu.setUpdateBy ( SecurityUtils.getUsername () );
        return toAjax ( menuService.updateMenu ( menu ) );
    }

    /**
     * 删除菜单
     */
    @ApiOperation ( "删除菜单" )
    @PreAuthorize ( "@ss.hasPermi('system:menu:remove')" )
    @Log ( title = "菜单管理", businessType = BusinessType.DELETE )
    @DeleteMapping ( "/{menuId}" )
    public AjaxResult remove ( @PathVariable ( "menuId" ) String menuId ) {
        if ( menuService.hasChildByMenuId ( menuId ) ) {
            return AjaxResult.error ( "存在子菜单,不允许删除" );
        }
        if ( menuService.checkMenuExistRole ( menuId ) ) {
            return AjaxResult.error ( "菜单已分配,不允许删除" );
        }
        return toAjax ( menuService.deleteMenuById ( menuId ) );
    }
}
